package com.theanh.RssActivity.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import com.theanh.RssActivity.R;
import com.theanh.RssActivity.Store;
import com.theanh.RssActivity.db.DbAdapter;
import com.theanh.RssActivity.entity.Channel;
import com.theanh.RssActivity.entity.Item;
import com.theanh.RssActivity.ui.adapter.ItemAdapter;
import com.theanh.RssActivity.ui.model.ChannelModel;
import com.theanh.RssActivity.ui.model.FinderModel;
import com.theanh.RssActivity.ui.model.ItemModel;
import com.theanh.RssActivity.updater.ChannelUpdater;
import com.theanh.RssActivity.updater.ImageItemUpdater;
import com.theanh.RssActivity.util.Constants;
import com.theanh.RssActivity.util.DbUtils;
import com.theanh.RssActivity.util.FileUtils;
import com.theanh.RssActivity.util.Paging;
import com.theanh.RssActivity.util.Utils;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.DatePicker;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.net.Uri;

public class ListItemScreen extends ListActivity {
	public static final String TAG = "ListItemScreen";
	private static final int BEGIN_UPDATE_CHANNEL_MESSAGE = 2;
	private static final int END_UPDATE_CHANNEL_MESSAGE = 3;
	private static final int UPDATE_ITEMS_IMAGE_MESSAGE = 4;
	private static final int PREV_MENU_ID = Menu.FIRST;
	private static final int UPDATE_MENU_ID = Menu.FIRST + 1;
	private static final int NEXT_MENU_ID = Menu.FIRST + 2;
	private static final int FILTER_MENU_ID = Menu.FIRST + 3;
	private static final int FIND_MENU_ID = Menu.FIRST + 4;
	private static final int FILTER_DIALOG_ID = 0;
	private MenuItem mnuPrev;
	private MenuItem mnuUpdate;
	private MenuItem mnuNext;
	private MenuItem mnuFilter;
	private MenuItem mnuFind;
	private Channel channel;
	private ItemAdapter itemAdapter;
	private Paging<Item> paging;
	private int currentPage = 1;
	private int numberItem;
	private int numberPage;
	private FinderModel finderModel;
	private String title ;
	List<Item> items = new ArrayList<Item>();
	
	private Thread updateThread;
	
	protected void sendMessage(int identifier) {
		Message message = new Message();
		message.what = identifier;

		// send data to update GUI
		handler.sendMessage(message);
	}
	
	private Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case END_UPDATE_CHANNEL_MESSAGE:
				if (itemAdapter != null){
					paging.setList(items);
					currentPage = 1;
					List<Item> listItem = paging.getPage(currentPage);
					itemAdapter.items = listItem;
				}
				//set title ListItemScreen
				int pageSize = Store.setting.getPageSize();
				numberItem = items.size();
				if(numberItem <= pageSize){
					numberPage = 1;
				}else{
					numberPage = numberItem/ pageSize;
					if(numberItem % pageSize >0){
						numberPage = numberItem/ pageSize +1;
					}
				}
				ListItemScreen.this.setTitle(title + " [page " + currentPage + "/"
						+ numberPage + "]");
				
				Store.channelModelSelected.updateNumberItem();
				// Set default focus
				setSelection(0);
				
				// Refresh all item in screen
				getListView().invalidateViews();
				
				// Enable menu Update
				if (mnuUpdate != null)
					mnuUpdate.setEnabled(true);
				
				// Make sure the progress bar is invisible
				setProgressBarIndeterminateVisibility(false);

				if (Store.setting.isDisplayImage()){
					// Call update image's item
					updateImageForItem();
				}
				
				break;
			case BEGIN_UPDATE_CHANNEL_MESSAGE:
				
				// Disable menu Update
				if (mnuUpdate != null)
					mnuUpdate.setEnabled(false);
				
				// Make sure the progress bar is invisible
				setProgressBarIndeterminateVisibility(true);
				
				break;
			case UPDATE_ITEMS_IMAGE_MESSAGE:
				
				break;
			}
			super.handleMessage(msg);
		}
	};

	private void updateImageForItem() {
		ImageItemUpdater imageUploader = new ImageItemUpdater();
		imageUploader.setItems(itemAdapter.items);
		imageUploader.setModels(itemAdapter.models);
		
		imageUploader.start();
	}
	
	private void init(){
		// Set channel
		DbAdapter dbAdapter = null;
		try {
			dbAdapter = DbUtils.createAndOpenDbAdapter();
			if(Store.setting.isHideReaded()){
				numberItem = (int) dbAdapter.getNumberItemUnRead(Store.channelModelSelected.channel);
			}else{
				numberItem = (int)dbAdapter.getNumberItem(Store.channelModelSelected.channel);
			}
		} catch (Exception ex) {
			Log.e(TAG, ex.toString());
		} finally {
			if (dbAdapter != null) {
				DbUtils.closeDbAdapter(dbAdapter);
			}
		}
		int pageSize = Store.setting.getPageSize();
		this.channel = Store.channelModelSelected.channel;
		if(numberItem <= pageSize){
			numberPage = 1;
		}else{
			numberPage = numberItem/ pageSize;
			if(numberItem % pageSize >0){
				numberPage = numberItem/ pageSize +1;
			}
		}
		this.setTitle(title + " [page " + currentPage + "/"
				+ numberPage + "]");
		// Set theme for list item
		this.setTheme(android.R.style.Theme_Light);
		
		Window w = getWindow();

		// Request for the progress bar to be shown in the title
		w.requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		w.requestFeature(Window.FEATURE_LEFT_ICON);

		setContentView(R.layout.list_item);
		
		// Make sure the progress bar is visible
		setProgressBarIndeterminateVisibility(true);
		
		//w.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.progressbar_3);
		showTitleIcon();
		
		// Set default focus
		//setSelection(0);

		// Create paging controller
		paging = new Paging<Item>();

		itemAdapter = new ItemAdapter(this, items);
		
		setListAdapter(itemAdapter);
		getListView().setItemsCanFocus(true);
		
		// Load data
		loadData();
		
		// Create finder view
		finderModel = FinderModel.createModel(this);
		
		finderModel.find.setOnClickListener(findOnClick);
		finderModel.close.setOnClickListener(closeOnClick);
	}
	
	private void showTitleIcon(){
		// Change icon
		Bitmap logo = null;
		Window w = getWindow();
		if (channel.getLogoUrl()!= null && channel.getLogoUrl().length() !=0){
			logo = FileUtils.loadImage(Constants.CHANNEL_LOGO_PREFIX + channel.getID());
			BitmapDrawable drawable = new BitmapDrawable(logo);
			w.setFeatureDrawable(Window.FEATURE_LEFT_ICON, drawable);
		}
		if (logo == null)
			w.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.progressbar_3);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		title = Store.categoryModelSelected.category
		.getName()
		+ "-" + Store.channelModelSelected.channel.getName();
		init();
		
	}

	private OnClickListener findOnClick = new OnClickListener() {
		public void onClick(View view) {
			// TODO: Call find method
			String input = ListItemScreen.this.finderModel.name.getText().toString();
			find(input);
			Log.i(TAG, "findOnClick::" + input);
			
		}
	};
	
	private OnClickListener closeOnClick = new OnClickListener() {
		public void onClick(View view) {
			ListItemScreen.this.finderModel.hide();
			loadData();
		}
	};
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		
		ItemModel model = (ItemModel)v.getTag();
		Log.i("ListItemScreen.onListItemClick", model.item.getUrl());
		
		Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(model.item.getUrl()));
		this.startActivity(intent);
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		
		mnuPrev = menu.add(0, PREV_MENU_ID, 2, R.string.menu_prev_text).setIcon(R.drawable.ic_prev_page);
		mnuUpdate = menu.add(0, UPDATE_MENU_ID, 3, R.string.menu_update_text).setIcon(R.drawable.ic_update);
		mnuNext = menu.add(0, NEXT_MENU_ID, 4, R.string.menu_next_text).setIcon(R.drawable.ic_next_page);
		mnuFilter = menu.add(0, FILTER_MENU_ID, 1, R.string.menu_filter_text).setIcon(R.drawable.ic_filter);
		mnuFind = menu.add(0, FIND_MENU_ID, 0, R.string.menu_find_text).setIcon(R.drawable.ic_menu_find);
		
		return true;
	}
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		if (currentPage == 1){
			mnuPrev.setEnabled(false);
		}
		if (currentPage == paging.getNumberPage()){
			mnuNext.setEnabled(false);
		}
		if (currentPage > 1 && currentPage < paging.getNumberPage()){
			mnuPrev.setEnabled(true);
			mnuNext.setEnabled(true);
		}
		if(currentPage>1 && currentPage == paging.getNumberPage()){
			mnuNext.setEnabled(false);
			mnuPrev.setEnabled(true);
		}
		if (1 >= paging.getNumberPage()){
			mnuPrev.setEnabled(false);
			mnuNext.setEnabled(false);
		}
		
		if (updateThread != null && updateThread.isAlive()){
			mnuUpdate.setTitle(R.string.menu_stop_update_channel_text);
			mnuUpdate.setIcon(R.drawable.ic_stop);
		} else{
			mnuUpdate.setTitle(R.string.menu_update_channel_text);
			mnuUpdate.setIcon(R.drawable.ic_update);
		}
		
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		
		switch (item.getItemId()) {
		case UPDATE_MENU_ID:
			if (updateThread == null || !updateThread.isAlive() || updateThread.getState() == Thread.State.TERMINATED){
				// Make sure the progress bar is visible
				setProgressBarIndeterminateVisibility(true);
				
				// Start update
				updateThread = new Thread(){
					public void run(){
						ChannelUpdater updater = new ChannelUpdater(Store.channelModelSelected.channel);
						updater.setModel(Store.channelModelSelected);
						updater.run();
						
						// Reload data
						loadData();
					}
				};
				try{
					updateThread.start();
				}catch(IllegalThreadStateException ex){
					Log.e(TAG, ex.toString());
				}
			} else {
				// Stop update
				try{
					updateThread.interrupt();
				}catch(SecurityException ex){
					Log.e(TAG, ex.toString());
				}
				
				// Make sure the progress bar is invisible
				setProgressBarIndeterminateVisibility(false);
			}
			break;
		case PREV_MENU_ID:
			if (currentPage > 1)
				currentPage--;
			List<Item> listItemPrev = paging.getPage(currentPage);
			itemAdapter.items = listItemPrev;
			getListView().invalidateViews();
			ListItemScreen.this.setTitle(title + " [page " + currentPage + "/"
					+ numberPage + "]");
			break;
		case NEXT_MENU_ID:
			if (currentPage < paging.getNumberPage())
				currentPage++;
			List<Item> listItemNext = paging.getPage(currentPage);
			itemAdapter.items = listItemNext;
			getListView().invalidateViews();
			ListItemScreen.this.setTitle(title + " [page " + currentPage + "/"
					+ numberPage + "]");
			break;
		case FILTER_MENU_ID:
			showDialog(FILTER_DIALOG_ID);
			break;
		case FIND_MENU_ID:
			finderModel.show();
			finderModel.name.setFocusable(true);
			break;
		}
		
		Log.i(TAG,"Current Page:" + currentPage);

		return super.onOptionsItemSelected(item);
	}
	
	private void loadData() {
		Thread thread = new Thread() {
			public void run() {
				beginUpdate();
				
				DbAdapter dbAdapter = null;
				try {
					dbAdapter = DbUtils.createAndOpenDbAdapter();
					items = dbAdapter.getItems(channel, !Store.setting.isHideReaded());
					
					// Load image for item
					for(Item item : items){
						item.setImage(FileUtils.loadImage(item.getID()));
					}
					
					// Sort list item by publishDate
					Collections.sort(items);
				} catch (Exception ex) {
					Log.e(TAG, ex.toString());
					//TODO: show message dialog
					
				} finally {
					// Close database
					DbUtils.closeDbAdapter(dbAdapter);
				}
				
				endUpdate();
			}
		};
		thread.setPriority(Thread.MIN_PRIORITY);
		thread.start();
	}
	
	public void beginUpdate(){
		sendMessage(BEGIN_UPDATE_CHANNEL_MESSAGE);
	}
	
	public void endUpdate(){
		sendMessage(END_UPDATE_CHANNEL_MESSAGE);
	}
	
	private void doFilter(final int year, final int month, final int day){
		Thread thread = new Thread(){
			public void run(){
				beginUpdate();
				
				Date date = new Date();
				date.setYear(year-1900);
				date.setMonth(month);
				date.setDate(day);
				date.setHours(0);
				date.setMinutes(0);
				date.setSeconds(0);
				
				Log.i(TAG, date.toString());
				
				DbAdapter dbAdapter = null;
				try{
					dbAdapter = DbUtils.createAndOpenDbAdapter();
					items = dbAdapter.getItemsByDate(ListItemScreen.this.channel, date);
					
					// Sort list item by publishDate
					Collections.sort(items);
				}catch(Exception ex){
					Log.e(TAG, ex.toString());
				}finally{
					DbUtils.closeDbAdapter(dbAdapter);
				}
				
				endUpdate();
			}
		};

		thread.setPriority(Thread.MIN_PRIORITY);
		thread.start();
	}
	
	private void find(final String itemTitle){
		Log.i(TAG, "find");

		Thread thread = new Thread(){
			public void run(){
				beginUpdate();
				
				DbAdapter dbAdapter = null;
				try{
					dbAdapter = DbUtils.createAndOpenDbAdapter();
					items = dbAdapter.findItemByTitle(ListItemScreen.this.channel, itemTitle);
					
					// Sort list item by publishDate
					Collections.sort(items);
				}catch(Exception ex){
					Log.e(TAG, ex.toString());
				}finally{
					DbUtils.closeDbAdapter(dbAdapter);
				}
				
				endUpdate();
			}
		};
		thread.setPriority(Thread.MIN_PRIORITY);
		thread.start();
	}
	@Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case FILTER_DIALOG_ID:
        	Date currentDateTime = Utils.getCurrentDateTime();
        	return new DatePickerDialog(this,
        			filterDateSetListener,
        			currentDateTime.getYear(), currentDateTime.getMonth(), currentDateTime.getDate());
        }
        
        return null;
	}
	
	 @Override
	    protected void onPrepareDialog(int id, Dialog dialog) {
	        switch (id) {
	        case FILTER_DIALOG_ID:
	        	Date currentDateTime = Utils.getCurrentDateTime();
	        	((DatePickerDialog) dialog).updateDate(currentDateTime.getYear(), currentDateTime.getMonth(), currentDateTime.getDate());
                break;
	        }
	 }
	 
	 private DatePickerDialog.OnDateSetListener filterDateSetListener =
         new DatePickerDialog.OnDateSetListener() {

             public void onDateSet(DatePicker view, int year, int monthOfYear,
                     int dayOfMonth) {
            	 Log.i(TAG, year +"/" + monthOfYear +"/" + dayOfMonth);
            	 
            	 doFilter(year,monthOfYear,dayOfMonth);
             }
         };
}
